package acs.offer.util;

import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;

import acs.offer.collection.Params;
import acs.offer.controller.EventBus;

public class DMSSoftTimer {
	// active items
	private  ConcurrentLinkedQueue<TimerItem> itemRegistered = new ConcurrentLinkedQueue<TimerItem>();
	// item pool for reuse
	private  ConcurrentLinkedQueue<TimerItem> itemPool = new ConcurrentLinkedQueue<TimerItem>();
	private Timer checkTimer;
	private long checkInterval = 10;

	private static DMSSoftTimer instance=new DMSSoftTimer();
	public static DMSSoftTimer getInstance() {
		return instance;
	}
	private DMSSoftTimer() {
		init();
	}

	private void init() {
		checkTimer = new Timer();

		// The timer can not be scheduled after it's cancelled, so there, the repeat
		// mode is using
		this.checkTimer.schedule(new TimerTask() {
			@Override
			public void run() {
				check();
			}
		}, this.checkInterval, this.checkInterval);

	}

	static class TimerItem {
		long startTime;
		long delay;
		int event;
		String sessionId;
		Params params;
	}

	private void check() {
		long currentTime;
		Iterator<TimerItem> itr;

		currentTime = System.currentTimeMillis();
		itr = itemRegistered.iterator();

		while (itr.hasNext()) {
			TimerItem item = itr.next();
			if ((item != null) && (item.delay <= (currentTime - item.startTime))) {
				if (itemRegistered.remove(item)) {
					Params param =item.params;
					if(param == null) {
						param = Params.build();
					}
					EventBus.getInstance().putMessage(item.event, param);
					// push into pool for re-use
					itemPool.add(item);
				}
			}
		}
	}
	
	public void startTimer(String sessionId,long delay, int event,Params params) {
		TimerItem timerItem = itemPool.poll();
		if (timerItem == null) {
			timerItem = new TimerItem();
		}

		timerItem.startTime = System.currentTimeMillis();
		timerItem.delay = delay;
		timerItem.event = event;
		timerItem.sessionId = sessionId;
		timerItem.params = params;

		itemRegistered.add(timerItem);
	}
	
	public void startTimer(long delay, int event,Params params) {
		this.startTimer(null, delay, event, params);
	}

	public void cancel(int event,String sessionId) {
		Iterator<TimerItem> iterator = itemRegistered.iterator();
		while(iterator.hasNext()) {
			TimerItem item = iterator.next();
			if(item.event == event && sessionId.equals(item.sessionId)) {
				iterator.remove();
				break;
			}
		}
	}
	public void startTimer(long delay, int event) {
		TimerItem timerItem = itemPool.poll();
		if (timerItem == null) {
			timerItem = new TimerItem();
		}

		timerItem.startTime = System.currentTimeMillis();
		timerItem.delay = delay;
		timerItem.event = event;

		itemRegistered.add(timerItem);
	}
}
